package com.tbit.uqbike.client.aop;

import com.tbit.uqbike.client.constant.annotation.TestAnnotation;
import com.tbit.uqbike.client.service.RedisService;
import com.tbit.uqbike.client.util.ResponseUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @Author: chen
 * @Description:
 * @Date: 创建于 11:45 2022/2/14
 */
@Component
@Aspect
public class TestAspect {

    @Autowired
    private RedisService redisService;

    /**
     * 定义切点
     */
    @Pointcut("@annotation(com.tbit.uqbike.client.constant.annotation.TestAnnotation)")
    public void TestAnnotation() {
    }

    /**
     * 环绕通知 （可以控制目标方法前中后期执行操作，目标方法执行前后分别执行一些代码）
     *
     * @param joinPoint
     * @return
     */
    @Before("TestAnnotation()")
    public void before(JoinPoint joinPoint) throws Exception {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        Assert.notNull(request, "request cannot be null.");
        //获取执行方法
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        //获取防重复提交注解
        TestAnnotation annotation = method.getAnnotation(TestAnnotation.class);

        //获取方法名称
        Signature signature = joinPoint.getSignature();

        if (!(signature instanceof MethodSignature)) {
            throw new RuntimeException("该注解只支持方法");
        }
        MethodSignature methodSignature = (MethodSignature) signature;

        String[] params = methodSignature.getParameterNames();
        Object[] args = joinPoint.getArgs();
        Boolean ble = false;
        for (int i = 0; i < args.length; i++) {
            if ("ble".equals(params[i])) {
                String bleString = String.valueOf(args[i]);
                if (bleString != null) {
                    ble = Boolean.valueOf(bleString);
                }
            }
        }
        String[] parameterNames = ((MethodSignature) signature).getParameterNames();
        // 获取token的下标
        int tokenIndex = ArrayUtils.indexOf(parameterNames, "token");
        // 获取token以及方法标记，生成redisKey和redisValue
        /*Object[] args = joinPoint.getArgs();*/
        String token = String.valueOf(args[tokenIndex]);

        String className = joinPoint.getTarget().getClass().getName();
        className = className.substring(className.lastIndexOf("."));
        String pointName = signature.getName();
        String redisKey = "unique." + token + className + "." + pointName;
        String redisValue = "1";
        if (redisService.get(redisKey) == null || ble) {
            //设置防重复操作限时标记（前置通知）
            redisService.add(redisKey, redisValue, (int) annotation.expireSeconds());
        } else {
            ResponseUtil.print(response, "{\"ret\":0,\"code\":\"-102\",\"msg\":\"请勿重复操作\"}");
        }

    }
}
